<script setup>
import { ref } from "vue";
import "@kitware/vtk.js/favicon";

// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import "@kitware/vtk.js/Rendering/Profiles/Geometry";
import vtkSphereSource from "@kitware/vtk.js/Filters/Sources/SphereSource";
import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
import vtkGenericRenderWindow from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
import vtkSTLReader from "@kitware/vtk.js/IO/Geometry/STLReader";
import { FieldAssociations } from "@kitware/vtk.js/Common/DataModel/DataSet/Constants";
// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------

let genericRenderWindow;
let renderer;
let renderWindow;
let resetCamera;
let render;
const renderContainer = ref();
const worldPosition = ref([]);
// ----------------------------------------------------------------------------
function initRender() {
  genericRenderWindow = vtkGenericRenderWindow.newInstance();
  genericRenderWindow.setContainer(renderContainer.value);
  renderer = genericRenderWindow.getRenderer();
  renderer.setViewport(0, 0, 1, 1);
  console.log(renderContainer, "render");
  genericRenderWindow.resize();

  renderWindow = genericRenderWindow.getRenderWindow();
  console.log("1");
  resetCamera = renderer.resetCamera;
  render = renderWindow.render;
}

function update(reader) {
  const mapper = vtkMapper.newInstance({ scalarVisibility: false });
  const actor = vtkActor.newInstance();
  actor.setMapper(mapper);
  mapper.setInputConnection(reader.getOutputPort());
  renderer.addActor(actor);
  resetCamera();
  render();
}

// ----------------------------------------------------------------------------
// Use a file reader to load a local file
// ----------------------------------------------------------------------------

function handleFile(event) {
  event.preventDefault();
  const dataTransfer = event.dataTransfer;
  const files = event.target.files || dataTransfer.files;
  initRender();
  let tasks = Array.from(files).map((file) => {
    return new Promise((resolve, reject) => {
      const fileReader = new FileReader();
      let reader = vtkSTLReader.newInstance();
      fileReader.onload = (e) => {
        reader.parseAsArrayBuffer(fileReader.result);
        update(reader);
        resolve();
      };
      fileReader.readAsArrayBuffer(file);
    });
  });
  Promise.all(tasks).then(() => {
    _3dClickListen();
    console.log("2");
  });
}

// ----------------------------------------------------------------------------
// 监听点击获取世界坐标
// ----------------------------------------------------------------------------
function _3dClickListen() {
  const interactor = renderWindow.getInteractor();
  const apiSpecificRenderWindow = interactor.getView();
  const hardwareSelector = apiSpecificRenderWindow.getSelector();
  hardwareSelector.setCaptureZValues(true);
  hardwareSelector.setFieldAssociation(
    FieldAssociations.FIELD_ASSOCIATION_CELLS
  );
  renderContainer.value.addEventListener("click", (event) => {
    const [x, y] = eventToWindowXY(event);

    hardwareSelector.getSourceDataAsync(renderer, x, y, x, y).then((result) => {
      if (result) {
        processSelections(result.generateSelection(x, y, x, y));
      } else {
        processSelections(null);
      }
    });
  });
}
function processSelections(selections) {
  if (!selections || selections.length === 0) {
    worldPosition.value = [];
    return;
  }

  const { worldPosition: rayHitWorldPosition } = selections[0].getProperties();
  worldPosition.value = rayHitWorldPosition;
  const sphereSource = vtkSphereSource.newInstance({
    phiResolution: 30,
    thetaResolution: 30,
    center: rayHitWorldPosition,
  });

  const sphereMapper = vtkMapper.newInstance();
  const sphereActor = vtkActor.newInstance();
  sphereActor.setMapper(sphereMapper);
  sphereActor.getProperty().setEdgeVisibility(true);
  sphereMapper.setInputConnection(sphereSource.getOutputPort());
  renderer.addActor(sphereActor);
  render();
}
function eventToWindowXY(event) {
  const interactor = renderWindow.getInteractor();
  const apiSpecificRenderWindow = interactor.getView();

  // 获取渲染容器的边界矩形
  const containerRect = renderContainer.value.getBoundingClientRect();

  // 计算鼠标点击位置相对于容器的坐标
  const { clientX, clientY } = event;
  const relativeX = clientX - containerRect.left;
  const relativeY = clientY - containerRect.top;

  // 获取渲染窗口的尺寸
  const [width, height] = apiSpecificRenderWindow.getSize();

  // 将相对坐标转换为渲染窗口坐标
  const x = Math.round((width * relativeX) / containerRect.width);
  const y = Math.round(height * (1 - relativeY / containerRect.height)); // 需要翻转Y坐标

  return [x, y];
}
</script>
<template>
  <input type="file" class="fileInput_local" @change="handleFile" multiple />
  <span>世界坐标：{{ worldPosition }}</span>
  <div class="mianContainer" ref="renderContainer"></div>
</template>
<style lang="scss" scoped>
.mianContainer {
  width: 100%;
  height: calc(100vh - 100px);
}
</style>
